package cn.signalpha.modules.auth.endpoint;

import cn.binarywang.wx.miniapp.api.WxMaLinkService;
import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaSecCheckService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.security.WxMaMsgSecCheckCheckRequest;
import cn.binarywang.wx.miniapp.bean.security.WxMaMsgSecCheckCheckResponse;
import cn.binarywang.wx.miniapp.bean.urllink.GenerateUrlLinkRequest;
import cn.signalpha.common.constant.AppConstant;
import cn.signalpha.common.utils.Assert;
import cn.signalpha.core.boot.ctrl.BaseController;
import cn.signalpha.core.log.exception.ServiceException;
import cn.signalpha.core.redis.cache.RedisCache;
import cn.signalpha.core.secure.TokenUser;
import cn.signalpha.core.tool.api.R;
import cn.signalpha.core.tool.utils.StringUtil;
import cn.signalpha.modules.auth.dto.MsgSecCheckDTO;
import cn.signalpha.modules.com.entity.UserOauth;
import cn.signalpha.modules.com.entity.enums.UserSourceEnum;
import cn.signalpha.modules.com.service.UserOauthService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Value;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.*;
import java.net.URLEncoder;
import java.time.Duration;

/**
 * 令牌端点
 */
@RestController
@AllArgsConstructor
@RequestMapping(AppConstant.APPLICATION_AUTH_NAME)
@Api(value = "微信小程序", tags = "微信小程序")
public class WxMaEndPoint extends BaseController  {

	private final RedisCache redisCache;
	private final WxMaService wxMaService;
	private final HttpServletResponse response;
	private final UserOauthService userOauthService;

	@GetMapping("/wechat/mobile")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "获取授权手机号", notes = "")
	public R oauthWechatMobile(@RequestParam String code) {
		WxMaPhoneNumberInfo phoneNoInfo;
		try {
			phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(code);
		} catch (WxErrorException e) {
			throw new ServiceException(StringUtil.format("错误码：{}， 错误信息{}", e.getError().getErrorCode(), e.getError().getErrorMsg()));
		}
		return R.data(phoneNoInfo.getPhoneNumber());
	}

	@GetMapping("/wechat/share/code")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "小程序二维码", notes = "")
	public void wechatShareCode(@RequestParam String url, @RequestParam String scene) {
		//获取配置的环境变量
		ConfigurableEnvironment environment = new StandardEnvironment();
		String activeProfiles = environment.getActiveProfiles()[0];
		boolean checkPath = true;
		String envVersion = "release";
		switch (activeProfiles) {
			case AppConstant.DEV_CODE:
				checkPath = false;
				envVersion = "develop";
				break;
			case AppConstant.TEST_CODE:
			case AppConstant.STAGING_CODE:
				checkPath = false;
				envVersion = "trial";
				break;
		}

		File file;
		WxMaQrcodeService wxMaQrcodeService = wxMaService.getQrcodeService();
		try {
			file = wxMaQrcodeService.createWxaCodeUnlimit(scene, url, checkPath, envVersion, 430, true, new WxMaCodeLineColor("0", "0", "0"), false);
		} catch (WxErrorException e) {
			throw new ServiceException(StringUtil.format("错误码：{}， 错误信息{}", e.getError().getErrorCode(), e.getError().getErrorMsg()));
		}

		try {
			FileInputStream fileInputStream = new FileInputStream(file);
			InputStream fis = new BufferedInputStream(fileInputStream);
			byte[] buffer = new byte[fis.available()];
			fis.read(buffer);
			fis.close();
			response.reset();
			response.setCharacterEncoding("UTF-8");
			response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("img.jpg", "UTF-8"));
			response.addHeader("Content-Length", "" + file.length());
			OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream");
			outputStream.write(buffer);
			outputStream.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@GetMapping("/wechat/share/code/set/scene")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "设置小程序二维码参数", notes = "参数过长调用，参数有效期90天")
	public R wechatShareCodeSetKey(@RequestParam String key, @RequestParam String scene) {
		redisCache.setEx(key, scene, Duration.ofDays(90));
		return R.status(true);
	}

	@GetMapping("/wechat/share/code/get/scene")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "获取小程序二维码参数", notes = "参数过长调用，参数有效期90天")
	public R wechatShareCodeGetKey(@RequestParam String key) {
		return R.data(redisCache.get(key));
	}

	@GetMapping("/wechat/url/link")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "获取URL Link", notes = "")
	public R oauthWechatUrlLink(@RequestParam String url, @RequestParam String query) {
		//获取配置的环境变量
		ConfigurableEnvironment environment = new StandardEnvironment();
		String activeProfiles = environment.getActiveProfiles()[0];
		String envVersion = "release";
		switch (activeProfiles) {
			case AppConstant.DEV_CODE:
				envVersion = "develop";
				break;
			case AppConstant.TEST_CODE:
			case AppConstant.STAGING_CODE:
				envVersion = "trial";
				break;
		}

		String urlLink;
		WxMaLinkService wxMaLinkService = wxMaService.getLinkService();
		try {
			urlLink = wxMaLinkService.generateUrlLink(GenerateUrlLinkRequest.builder()
				.path(url).query(query).expireType(1).expireInterval(30).envVersion(envVersion).build()
			);
		} catch (WxErrorException e) {
			throw new ServiceException(StringUtil.format("错误码：{}， 错误信息{}", e.getError().getErrorCode(), e.getError().getErrorMsg()));
		}
		return R.data(urlLink);
	}

	@PostMapping("/wechat/msg/sec/check")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "文本内容安全识别", notes = "")
	public R msgSecCheck(@Valid @RequestBody MsgSecCheckDTO msgSecCheckDTO) {
		TokenUser tokenUser = getUser();
		Assert.isNull(tokenUser, "未获取到用户信息");
		UserOauth userOauth = userOauthService.getByUserIdAndSource(tokenUser.getUserId(), UserSourceEnum.WECHAT_MINI_APP.getValue());
		Assert.isNull(userOauth, "未获取到用户openId");

		WxMaSecCheckService wxMaSecCheckService = wxMaService.getSecCheckService();
		try {
			WxMaMsgSecCheckCheckResponse wxMaMsgSecCheckCheckResponse = wxMaSecCheckService.checkMessage(WxMaMsgSecCheckCheckRequest
				.builder().version("2").openid(userOauth.getOpenId()).content(msgSecCheckDTO.getContent()).scene(msgSecCheckDTO.getType()).build()
			);
			if(wxMaMsgSecCheckCheckResponse.getErrcode() != 0){
				throw new ServiceException(wxMaMsgSecCheckCheckResponse.getErrmsg());
			}
			if(!"pass".equals(wxMaMsgSecCheckCheckResponse.getResult().getSuggest())){
				throw new ServiceException("文本内容违规");
			}
		} catch (WxErrorException e) {
			throw new ServiceException(StringUtil.format("错误码：{}， 错误信息{}", e.getError().getErrorCode(), e.getError().getErrorMsg()));
		}
		return R.status(true);
	}

}
